<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>Query-Time Search-as-You-Type | Elasticsearch: The Definitive Guide [2.x] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch: The Definitive Guide [2.x]">
<link rel="up" href="partial-matching.html" title="Partial Matching">
<link rel="prev" href="_wildcard_and_regexp_queries.html" title="wildcard and regexp Queries">
<link rel="next" href="_index_time_optimizations.html" title="Index-Time Optimizations">
<meta name="DC.type" content="Learn/Docs/Legacy/Elasticsearch/Definitive Guide/2.x">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="2.x">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<p>
  <strong>WARNING</strong>: The 2.x versions of Elasticsearch have passed their
  <a href="https://www.elastic.co/support/eol">EOL dates</a>. If you are running
  a 2.x version, we strongly advise you to upgrade.
</p>
<p>
  This documentation is no longer maintained and may be removed. For the latest
  information, see the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">current
  Elasticsearch documentation</a>.
</p>
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: The Definitive Guide [2.x]</a></span>
»
<span class="breadcrumb-link"><a href="search-in-depth.html">Search in Depth</a></span>
»
<span class="breadcrumb-link"><a href="partial-matching.html">Partial Matching</a></span>
»
<span class="breadcrumb-node">Query-Time Search-as-You-Type</span>
</div>
<div class="navheader">
<span class="prev">
<a href="_wildcard_and_regexp_queries.html">« wildcard and regexp Queries</a>
</span>
<span class="next">
<a href="_index_time_optimizations.html">Index-Time Optimizations »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="_query_time_search_as_you_type"></a>Query-Time Search-as-You-Type<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/130_Partial_Matching/20_Match_phrase_prefix.asciidoc">edit</a>
</h2>
</div></div></div>
<p>Leaving postcodes behind, let’s take a look at how prefix matching can help
with full-text queries.  Users have become accustomed to seeing search results
before they have finished typing their query—​so-called <em>instant search</em>, or
<em>search-as-you-type</em>.  Not only do users receive their search results in less
time, but we can guide them toward results that actually exist in our index.</p>
<p>For instance, if a user types in <code class="literal">johnnie walker bl</code>, we would like to show results for Johnnie Walker Black Label and Johnnie Walker Blue
Label before they can finish typing their query.</p>
<p>As always, there are more ways than one to skin a cat! We will start by
looking at the way that is simplest to implement.  You don’t need to prepare your
data in any way; you can implement <em>search-as-you-type</em> at query time on any
full-text field.</p>
<p>In <a class="xref" href="phrase-matching.html" title="Phrase Matching">Phrase Matching</a>, we introduced the <code class="literal">match_phrase</code> query, which matches
all the specified words in the same positions relative to each other.  For-query time search-as-you-type, we can use a specialization of this query,
called the <code class="literal">match_phrase_prefix</code> query:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">{
    "match_phrase_prefix" : {
        "brand" : "johnnie walker bl"
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/130_Partial_Matching/20_Match_phrase_prefix.json"></div>
<p>This query behaves in the same way as the <code class="literal">match_phrase</code> query, except that it
treats the last word in the query string as a prefix.  In other words, the
preceding example would look for the following:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">johnnie</code>
</li>
<li class="listitem">
Followed by <code class="literal">walker</code>
</li>
<li class="listitem">
Followed by words beginning with <code class="literal">bl</code>
</li>
</ul>
</div>
<p>If you were to run this query through the <code class="literal">validate-query</code> API, it would
produce this explanation:</p>
<pre class="literallayout">"johnnie walker bl*"</pre>

<p>Like the <code class="literal">match_phrase</code> query, it accepts a <code class="literal">slop</code> parameter (see <a class="xref" href="slop.html" title="Mixing It Up">Mixing It Up</a>) to
make the word order and relative positions somewhat less rigid:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">{
    "match_phrase_prefix" : {
        "brand" : {
            "query": "walker johnnie bl", <a id="CO94-1"></a><i class="conum" data-value="1"></i>
            "slop":  10
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/130_Partial_Matching/20_Match_phrase_prefix.json"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO94-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>Even though the words are in the wrong order, the query still matches
because we have set a high enough <code class="literal">slop</code> value to allow some flexibility
in word positions.</p>
</td>
</tr>
</table>
</div>
<p>However, it is always only the last word in the query string that is treated
as a prefix.</p>
<p>Earlier, in <a class="xref" href="prefix-query.html" title="prefix Query">prefix Query</a>, we warned about the perils of the prefix—​how
<code class="literal">prefix</code> queries can be resource intensive.  The same is true in this
case.  A prefix of <code class="literal">a</code> could match hundreds of thousands of terms. Not only
would matching on this many terms be resource intensive, but it would also not be
useful to the user.</p>
<p>We can limit the impact of the prefix expansion by setting <code class="literal">max_expansions</code> to
a reasonable number, such as 50:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">{
    "match_phrase_prefix" : {
        "brand" : {
            "query":          "johnnie walker bl",
            "max_expansions": 50
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/130_Partial_Matching/20_Match_phrase_prefix.json"></div>
<p>The <code class="literal">max_expansions</code> parameter controls how many terms the prefix is allowed
to match.  It will find the first term starting with <code class="literal">bl</code> and keep collecting
terms (in alphabetical order) until it either runs out of terms with prefix
<code class="literal">bl</code>, or it has more terms than <code class="literal">max_expansions</code>.</p>
<p>Don’t forget that we have to run this query every time the user types another
character, so it needs to be fast.  If the first set of results isn’t what users are after, they’ll keep typing until they get the results that they want.</p>
</div>
<div class="navfooter">
<span class="prev">
<a href="_wildcard_and_regexp_queries.html">« wildcard and regexp Queries</a>
</span>
<span class="next">
<a href="_index_time_optimizations.html">Index-Time Optimizations »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
